001 /* 002 * Copyright 2006 Stephen J. McConnell. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package net.dpml.component; 020 021 import java.io.IOException; 022 import java.net.URI; 023 import java.lang.ref.WeakReference; 024 025 import net.dpml.lang.Classpath; 026 import net.dpml.lang.Info; 027 import net.dpml.lang.Part; 028 029 import net.dpml.util.Logger; 030 031 /** 032 * Component composition. 033 * 034 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 035 * @version 1.0.1 036 */ 037 public abstract class Composition extends Part implements Directive 038 { 039 private final Directive m_directive; 040 private final Controller m_controller; 041 042 private transient WeakReference m_model; 043 044 /** 045 * Creation of a new abstract composition instance. 046 * @param logger the assigned logging channel 047 * @param info the part info descriptor 048 * @param classpath the part classpath definition 049 * @param controller the part controller 050 * @param directive the part deployment strategy directive 051 * @param label debug label 052 * @exception IOException if an I/O error occurs 053 */ 054 public Composition( 055 Logger logger, Info info, Classpath classpath, Controller controller, 056 Directive directive, String label ) throws IOException 057 { 058 super( logger, info, classpath, label ); 059 060 if( null == directive ) 061 { 062 throw new NullPointerException( "directive" ); 063 } 064 m_directive = directive; 065 m_controller = controller; 066 } 067 068 /** 069 * Return the assigned controller. 070 * @return the controller 071 */ 072 public Controller getController() 073 { 074 return m_controller; 075 } 076 077 /** 078 * Return the part content or null if the result type is unresolvable 079 * relative to the supplied class argument. Class types recognized over and 080 * above the Part class include Directive, Model, Component and Controller. 081 * 082 * @param c the content class 083 * @return the content 084 * @exception IOException if an IO error occurs 085 */ 086 protected Object getContent( Class c ) throws IOException 087 { 088 if( Directive.class.isAssignableFrom( c ) ) 089 { 090 return m_directive; 091 } 092 else if( Model.class.isAssignableFrom( c ) ) 093 { 094 return getModel(); 095 } 096 else if( Component.class.isAssignableFrom( c ) ) 097 { 098 return newComponent(); 099 } 100 else if( Controller.class.isAssignableFrom( c ) ) 101 { 102 return m_controller; 103 } 104 else 105 { 106 return super.getContent( c ); 107 } 108 } 109 110 /** 111 * Get the deployment directive. 112 * @return the deployment directive 113 */ 114 public Directive getDirective() 115 { 116 return m_directive; 117 } 118 119 /** 120 * Get the deployment model. 121 * @return the deployment model 122 */ 123 public Model getModel() 124 { 125 if( null != m_model ) 126 { 127 Model model = (Model) m_model.get(); 128 if( null != model ) 129 { 130 return model; 131 } 132 } 133 try 134 { 135 Model model = m_controller.createModel( this ); 136 m_model = new WeakReference( model ); 137 return model; 138 } 139 catch( Throwable e ) 140 { 141 URI uri = m_controller.getURI(); 142 final String error = 143 "Unexpected error while attempting to create a component model." 144 + "\nDirective: " + m_directive; 145 throw new ControlRuntimeException( uri, error, e ); 146 } 147 } 148 149 /** 150 * Create and return a new component using the deplyment model established by the part. 151 * @return the component 152 */ 153 public Component newComponent() 154 { 155 Model model = getModel(); 156 try 157 { 158 return m_controller.createComponent( model ); 159 } 160 catch( Throwable e ) 161 { 162 URI uri = m_controller.getURI(); 163 final String error = 164 "Unexpected error while attempting to create a component." 165 + "\nDirective: " + m_directive; 166 throw new ControlRuntimeException( uri, error, e ); 167 } 168 } 169 170 /** 171 * Instantiate a value. 172 * @param args supplimentary arguments 173 * @return the resolved instance 174 * @exception Exception if a deployment error occurs 175 */ 176 public Object instantiate( Object[] args ) throws Exception 177 { 178 Component component = newComponent(); 179 return component.getProvider().getValue( false ); 180 } 181 182 /** 183 * Return true if this object is equal to the supplied object. 184 * @param other the object to evaluate 185 * @return the equality status 186 */ 187 public boolean equals( Object other ) 188 { 189 if( super.equals( other ) && ( other instanceof Composition ) ) 190 { 191 Composition composite = (Composition) other; 192 if( !m_directive.equals( composite.m_directive ) ) 193 { 194 return false; 195 } 196 else 197 { 198 if( null == m_controller ) 199 { 200 return null == composite.m_controller; 201 } 202 else 203 { 204 return m_controller.equals( composite.m_controller ); 205 } 206 } 207 } 208 else 209 { 210 return false; 211 } 212 } 213 214 /** 215 * Return the hashcode for the instance. 216 * @return the instance hashcode 217 */ 218 public int hashCode() 219 { 220 int hash = super.hashCode(); 221 hash ^= m_directive.hashCode(); 222 if( null != m_controller ) 223 { 224 hash ^= m_controller.hashCode(); 225 } 226 return hash; 227 } 228 }